import java.util.*;
import java.awt.Point;

/**
 * Node knows it's connections to other nodes and has several different ways to
 * access them.
 * It also knows where on the map it is positioned so that it can be drawn by
 * the GUI.
 */
class Node
{
    private final int n;

    // All connections
    private IdentityHashMap<Node, TreeSet<Integer>> connections;

    // Special connections
    private LinkedList<Node> t;
    private LinkedList<Node> u;
    private LinkedList<Node> b;
    private LinkedList<Node> x;
    private Point mapPosition;


    public Node(int n) {
        this.n = n;

        this.connections = new IdentityHashMap<Node, TreeSet<Integer>>();
        this.t = new LinkedList<Node>();
        this.u = new LinkedList<Node>();
        this.b = new LinkedList<Node>();
        this.x = new LinkedList<Node>();
        this.mapPosition = new Point();
    }

    public Node(int n, int x, int y) {
        this.n = n;

        this.connections = new IdentityHashMap<Node, TreeSet<Integer>>();
        this.t = new LinkedList<Node>();
        this.u = new LinkedList<Node>();
        this.b = new LinkedList<Node>();
        this.x = new LinkedList<Node>();
        this.mapPosition = new Point(x, y);
    }

    public int getNum()
    {
        return this.n;
    }

    /**
     * @return iterator over all Connections.
     */
    public Set<Node> connectedNodes() {
        return this.connections.keySet();
    }

    /**
     * @return iterator over all Connection types.
     */
    public TreeSet<Integer> waysConnected(Node to) {
        return this.connections.get(to);
    }

    /**
     * @return iterator over all Taxi neighbours.
     */
    public Iterator<Node> t_neighbours() {
        return this.t.listIterator(0);
    }

    /**
     * @return iterator over all Tube neighbours.
     */
    public Iterator<Node> u_neighbours() {
        return this.u.listIterator(0);
    }

    /**
     * @return iterator over all Bus neighbours.
     */
    public Iterator<Node> b_neighbours() {
        return this.b.listIterator(0);
    }

    /**
     * @return iterator over all Boat neighbours.
     */
    public Iterator<Node> x_neighbours() {
        return this.x.listIterator(0);
    }

    /**
     * @return the position of the node on the map image
     */
    public Point getMapPosition() {
        return this.mapPosition;
    }

    /**
     * Set the position of the node on the map
     */
    public Point setMapPosition(int x, int y) {
        this.mapPosition.move(x, y);
        return this.mapPosition;
    }

    public void addConnection(Node to, int type) {
        switch (type) {
            case Agent.TAXI:
                this.t.add(to);
                break;
            case Agent.UNDERGROUND:
                this.u.add(to);
                break;
            case Agent.BUS:
                this.b.add(to);
                break;
            case Agent.BLACK:
                this.x.add(to);
                break;
        }
        if (!this.connections.containsKey(to)) {
            this.connections.put(to, new TreeSet<Integer>());
        }
        this.connections.get(to).add(type);
    }

    public boolean isConnected(Node to) {
        return this.connections.containsKey(to.getNum());
    }

}
